package jys.test.yddata.utils;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.FileUtils;
import android.provider.Settings;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

import jys.test.yddata.pictureselector.PermissionUtils;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class ClientManager {
    protected AppCompatActivity app;
    protected OkHttpClient client;
    protected String socketUrl;
    protected Map<String, String> baseKey;
    protected Consumer<Boolean> responseFunc;

    /**
     * 初始化服务
     * @param appCompatActivity APP界面
     * @param response 请求处理状态回调方法
     * @param url 服务器地址
     */
    protected ClientManager(AppCompatActivity appCompatActivity, Consumer<Boolean> response, String url) {
        app = appCompatActivity;
        client = new OkHttpClient();
        socketUrl = url;
        baseKey = new HashMap<>();
        responseFunc = response;
    }

    /**
     * 添加POST请求时的固定参数（验证信息等）
     * @param key 键
     * @param value 值
     */
    protected void addBaseKey(String key, String value) {
        baseKey.put(key, value);
    }

    /**
     * 转储外部存储的图片
     * @param extpath 来自外部存储的图片文件路径
     */
    public String getFigFromExt(String extpath) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            String pslpath = app.getBaseContext().getCacheDir().getPath()+"/FIG.jpg";
            InputStream is = null;
            FileOutputStream fos = null;
            try {
                ContentResolver contentResolver = app.getContentResolver();
                is = contentResolver.openInputStream(Uri.parse("file://"+extpath));
                File cache = new File(pslpath);
                fos = new FileOutputStream(cache);
                FileUtils.copy(is, fos);
            } catch (IOException e) {
                e.printStackTrace();
                return "";
            } finally {
                if (fos!=null)
                    try { fos.close(); } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                if (is!=null)
                    try { is.close(); } catch (IOException ex) {
                        ex.printStackTrace();
                    }
            }
            return pslpath;
        } else {
            return extpath;
        }
    }

    private boolean requestPermission() {
        //请求应用需要的所有权限
        PermissionUtils.checkPermissionFirst(app,  1024,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA});

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // 先判断有没有权限
            if (Environment.isExternalStorageManager()) {
                return true;
            } else {
                Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                intent.setData(Uri.parse("package:" + app.getPackageName()));
                app.startActivityForResult(intent, 1024);
                return false;
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 先判断有没有权限
            if (ActivityCompat.checkSelfPermission(app, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(app, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                return true;
            } else {
                ActivityCompat.requestPermissions(app, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1024);
                return false;
            }
        } else {
            return true;
        }
    }

    /**
     * 发送采集到的图片及标签
     * @param filepath 图片文件路径
     * @param label 图片标签
     */
    public void sendFigLabel(String filepath, String label) {
        if (!checkNetworkOK()) return;

        File file = new File(filepath);

        MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("label", label)
                .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("file/*"), file));
        for (Map.Entry<String, String> entry : baseKey.entrySet()) {
            multipartBodyBuilder.addFormDataPart(entry.getKey(), entry.getValue());
        }

        Request request = new Request.Builder()
                .url(socketUrl)
                .post(multipartBodyBuilder.build())
                .build();

        client.newCall(request).enqueue(requestCallback);
    }

    /**
     * 依照网络状态对用户提示
     */
    protected boolean checkNetworkOK() {
        if(!isNetworkConnected()){
            remind2User(false, "请检查网络连接");
            return false;
        }
        return true;
    }

    /**
     * 判断网络状态
     */
    private boolean isNetworkConnected() {
        if (app != null) {
            ConnectivityManager mConnectivityManager = (ConnectivityManager) app.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
            if (mNetworkInfo != null)
                return mNetworkInfo.isAvailable();
        }
        return false;
    }

    protected Callback requestCallback = new Callback() {     // 请求回调
        @Override
        public void onFailure(@NotNull Call call, IOException e) {
            remind2User(false, "请求失败，Exp ["+e.getMessage()+"]");
            e.printStackTrace();
        }

        @Override
        public void onResponse(@NotNull Call call, Response response) throws IOException {
            if (response.code() != 200) {
                remind2User(false, "请求失败，CODE ["+response.code()+"]");
            } else if (response.body() == null) {
                remind2User(false, "请求失败，服务器信息 [null]");
            } else if (response.body().string().equals("success")) {
                remind2User(true, "上传成功!");
            } else {
                remind2User(false, "请求失败，服务器信息 ["+response.body().string()+"]");
            }
        }
    };

    protected void remind2User(boolean isOK, String message) {
        app.runOnUiThread(()->{
            Toast.makeText(app, message, Toast.LENGTH_SHORT).show();
            responseFunc.accept(isOK);
        });
    }

    public static class Builder {
        private boolean inited = false;
        private ClientManager clientManager;

        public Builder init(AppCompatActivity appCompatActivity, Consumer<Boolean> response, String url) {
            inited = true;
            clientManager = new ClientManager(appCompatActivity, response, url);
            return this;
        }

        @SuppressLint("Assert")
        public ClientManager build() {
            assert inited;
            clientManager.requestPermission();
            return clientManager;
        }

        @SuppressLint("Assert")
        public Builder addBaseKey(String key, String value) {
            assert inited;
            clientManager.addBaseKey(key, value);
            return this;
        }
    }
}
